package com.kun.video.domain;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Point2D;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.co.caprica.vlcj.player.base.MediaPlayer;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.function.Consumer;

/**
 * 视频水印框选器（支持实时显示选择框）
 */
public class WatermarkSelector {
    private static final Logger log = LoggerFactory.getLogger(WatermarkSelector.class);
    /**
     * 小数点计算精度位数
     */
    private final int scale = 20;

    // 样式配置
    private final ObjectProperty<Color> strokeColor = new SimpleObjectProperty<>(Color.GREEN);
    private final ObjectProperty<Double> strokeWidth = new SimpleObjectProperty<>(1.0);

    // 核心组件
    private final Rectangle selectionRect = new Rectangle();
    private final ImageView imageView;
    private final MediaPlayer mediaPlayer;
    private final Pane drawingPane;

    // 状态跟踪
    private double startX, startY;
    private boolean isActive = false;

    private Consumer<Double[]> selectorConsumer;

    public WatermarkSelector(ImageView imageView, MediaPlayer mediaPlayer) {
        this.imageView = imageView;
        this.mediaPlayer = mediaPlayer;
        this.drawingPane = wrapImageView();
        initSelector();
    }

    public void setSelectorConsumer(Consumer<Double[]> selectorConsumer) {
        this.selectorConsumer = selectorConsumer;
    }

    private Pane wrapImageView() {
        // 创建新的绘制容器
        Pane container = new Pane(imageView);
        container.setStyle("-fx-border-width: 1px;-fx-border-color: red");
        container.setPickOnBounds(false);
        // 绑定尺寸同步
        imageView.fitWidthProperty().addListener((obs, ov, nv) -> {
            container.setPrefWidth(nv.doubleValue());
            container.setMinWidth(nv.doubleValue());
            container.setMaxWidth(nv.doubleValue());
        });
        imageView.fitHeightProperty().addListener((obs, ov, nv) -> {
            container.setPrefHeight(nv.doubleValue());
            container.setMinHeight(nv.doubleValue());
            container.setMaxHeight(nv.doubleValue());
        });
        return container;
    }

    private void initSelector() {
        // 初始化矩形样式
        selectionRect.setFill(Color.TRANSPARENT);
        selectionRect.strokeProperty().bind(strokeColor);
        selectionRect.strokeWidthProperty().bind(strokeWidth);
        selectionRect.setVisible(false);

        // 添加矩形到专用绘制层
        drawingPane.getChildren().add(selectionRect);

        // 绑定事件处理
        imageView.addEventHandler(MouseEvent.MOUSE_PRESSED, this::handlePress);
        imageView.addEventHandler(MouseEvent.MOUSE_DRAGGED, this::handleDrag);
        imageView.addEventHandler(MouseEvent.MOUSE_RELEASED, this::handleRelease);
    }

    // 事件处理方法
    private void handlePress(MouseEvent event) {
        if (!event.isPrimaryButtonDown()) {
            return;
        }

        startX = event.getX();
        startY = event.getY();

        selectionRect.setX(startX);
        selectionRect.setY(startY);
        selectionRect.setWidth(0);
        selectionRect.setHeight(0);
        selectionRect.setVisible(true);
        isActive = true;
        log.debug("开始框选 @ ({}, {})", startX, startY);
    }

    private void handleDrag(MouseEvent event) {
        if (!isActive) {
            return;
        }

        updateRectDimensions(event.getX(), event.getY());
        log.trace("框选更新: {}", getCurrentSelection());
    }

    private void handleRelease(MouseEvent event) {
        if (!isActive) {
            return;
        }

        isActive = false;
        selectionRect.setVisible(false);
        double[] currentSelection = getCurrentSelection();
        log.info("框选完成: {}", currentSelection);
        if (this.selectorConsumer != null) {
            this.selectorConsumer.accept(new Double[]{currentSelection[0], currentSelection[1], currentSelection[2], currentSelection[3]});
        }
    }

    private double[] convertToVideoCoordinates() {
        int videoWidth = mediaPlayer.video().videoDimension().width;
        int videoHeight = mediaPlayer.video().videoDimension().height;
        Point2D imageViewPoint = imageView.sceneToLocal(selectionRect.getX(), selectionRect.getY(), true);
        double zoomRatio = calculateZoomRatio(videoWidth, videoHeight, drawingPane.getPrefWidth(), drawingPane.getPrefHeight());
        BigDecimal zoomRatioBigDecimal = new BigDecimal(zoomRatio);
        double screenX = BigDecimal.valueOf(imageViewPoint.getX()).divide(zoomRatioBigDecimal, scale, RoundingMode.HALF_DOWN).doubleValue();
        double screenY = BigDecimal.valueOf(imageViewPoint.getY()).divide(zoomRatioBigDecimal, scale, RoundingMode.HALF_DOWN).doubleValue();
        double screenW = BigDecimal.valueOf(selectionRect.getWidth()).divide(zoomRatioBigDecimal, scale, RoundingMode.HALF_DOWN).doubleValue();
        double screenH = BigDecimal.valueOf(selectionRect.getHeight()).divide(zoomRatioBigDecimal, scale, RoundingMode.HALF_DOWN).doubleValue();
        return new double[]{screenX, screenY, screenW, screenH};
    }

    /**
     * 计算缩放比例
     *
     * @param videoWidth   视频原始宽度
     * @param videoHeight  视频原始高度
     * @param windowWidth  窗口宽度
     * @param windowHeight 窗口高度
     * @return 视频等比例缩放后放到窗口中的缩放比例
     */
    private double calculateZoomRatio(double videoWidth, double videoHeight, double windowWidth, double windowHeight) {
        // 视频宽高比例
        double videoResolutionRatio = new BigDecimal(videoWidth).divide(BigDecimal.valueOf(videoHeight), scale, RoundingMode.HALF_DOWN).doubleValue();
        // 窗口宽高比例
        double windowResolutionRatio = new BigDecimal(windowWidth).divide(BigDecimal.valueOf(windowHeight), scale, RoundingMode.HALF_DOWN).doubleValue();
        double targetWidthRatio = 1;
        double targetHeightRatio = 1;
        // 如果 videoResolutionRatio > videoResolutionRatio，高度为约束方向，按目标高度缩放。
        if (videoResolutionRatio > windowResolutionRatio) {
            targetWidthRatio = new BigDecimal(windowWidth).divide(BigDecimal.valueOf(videoWidth), scale, RoundingMode.HALF_DOWN).doubleValue();
        }
        // 如果 videoResolutionRatio < videoResolutionRatio，宽度为约束方向，按目标宽度缩放。
        if (videoResolutionRatio < windowResolutionRatio) {
            targetHeightRatio = new BigDecimal(windowHeight).divide(BigDecimal.valueOf(videoHeight), scale, RoundingMode.HALF_DOWN).doubleValue();
        }
        double min = Math.min(targetWidthRatio, targetHeightRatio);
//        log.info("视频宽度 -> {}，高度 ->{}，宽高比 -> {}。 窗口宽度 -> {}，高度 -> {}，宽高比 ->{}。    缩放比例 -> {}",
//                videoWidth, videoHeight, videoResolutionRatio, windowWidth, windowHeight, windowResolutionRatio, min);
        return min;
    }

    // 核心逻辑
    private void updateRectDimensions(double currentX, double currentY) {
        double minX = Math.min(startX, currentX);
        double minY = Math.min(startY, currentY);
        double width = Math.abs(currentX - startX);
        double height = Math.abs(currentY - startY);

        selectionRect.setX(minX);
        selectionRect.setY(minY);
        selectionRect.setWidth(width);
        selectionRect.setHeight(height);
    }

    // 坐标转换
    private double[] getCurrentSelection() {
        return convertToVideoCoordinates();
//        return convertToVideoCoordinates(
//                selectionRect.getX(),
//                selectionRect.getY(),
//                selectionRect.getWidth(),
//                selectionRect.getHeight()
//        );
    }


    private double[] convertToVideoCoordinates(double uiX, double uiY, double uiW, double uiH) {
        // 将鼠标事件坐标转换为 ImageView 的本地坐标（关键修正）
        Point2D imageViewPoint = imageView.sceneToLocal(uiX, uiY, true);

        double relativeX = imageViewPoint.getX();
        double relativeY = imageViewPoint.getY();

        // 边界校验
        relativeX = Math.max(0, Math.min(relativeX, imageView.getFitWidth()));
        relativeY = Math.max(0, Math.min(relativeY, imageView.getFitHeight()));

        // 获取视频原始尺寸（确保非零）
        int videoWidth = mediaPlayer.video().videoDimension().width;
        int videoHeight = mediaPlayer.video().videoDimension().height;
        if (videoWidth <= 0 || videoHeight <= 0) {
            return new double[]{0, 0, 0, 0};
        }

        // 计算缩放比例（添加安全校验）
        double scaleX = (imageView.getFitWidth() > 0) ? videoWidth / imageView.getFitWidth() : 1.0;
        double scaleY = (imageView.getFitHeight() > 0) ? videoHeight / imageView.getFitHeight() : 1.0;
//        System.out.println(StrUtil.format("视图w:{}，h:{}，框选坐标x:{}，y:{}，视频原尺寸w:{}，y:{}",
//                imageView.getFitWidth(), imageView.getFitHeight(), relativeX, relativeY, videoWidth, videoHeight));
        return new double[]{
                relativeX * scaleX,
                relativeY * scaleY,
                uiW * scaleX,
                uiH * scaleY
        };
    }

    // 配置方法
    public void setStrokeColor(Color color) {
        strokeColor.set(color);
    }

    public void setStrokeWidth(double width) {
        strokeWidth.set(width);
    }

    // 访问方法
    public Pane getDrawingPane() {
        return drawingPane;
    }

    public double[] getSelection() {
        return isActive ? null : getCurrentSelection();
    }

    public void reset() {
        selectionRect.setWidth(0);
        selectionRect.setHeight(0);
        isActive = false;
    }
}